
import pandas as pd
import os
from pandas.io.json import json_normalize
from openpyxl import load_workbook
import openpyxl
from time import localtime,strftime
from utils.option_parameter_config import Construct_config
'''
    当字典结构变复杂，即出现多层字典嵌套，方法就不适用了
'''



para_list=['dataset_file','device','initializer','model_class','optimizer']

class RecordHyperParameter:
    ''''
        记录超参数和效果
        如果加入了新参数，那原来的数据表如何处理？
    '''
    def __init__(self,result:dict,opt,filename):
        self.opt=opt
        self.filename=filename
        self.result=result

    def _read_record(self):
        args = vars(self.opt)
        dict={}
        for arg in args:
            dict[arg]=args[arg]
        return dict



    def write(self):
        cwdpath = os.getcwd()  #在程序运行时，当前目录就是根目录？
        filepath = cwdpath+'/'+strftime("%y%m%d", localtime())+self.filename  #不重复的文件记录，linux系统上的路径要用反斜杠
        print(filepath)
        dictionary=self._read_record()
        new_dictionary={}
        for key in self.result:
            new_dictionary[key]=self.result[key]
        for key in sorted(dictionary):
            if not (key in para_list):
                if isinstance(dictionary[key],list):
                    text=""
                    for it in dictionary[key]:
                        text+=it+';'
                    new_dictionary[key]=text
                else:new_dictionary[key] = dictionary[key]

        sheet_name = new_dictionary['model_name']  # 按照模型名字来获取表
        #print(new_dictionary)

        if not os.path.exists(filepath):
            print('-'*50,"creating a recordFile",'-'*50)
            df = pd.DataFrame(new_dictionary, index=[1])
            df.to_excel(filepath, sheet_name=sheet_name)
            if os.path.exists(filepath):
                print('-'*50,"successfully create a new recordFile:{}".format(filepath),'-'*50,)
            else:print('-'*50,'?'*20,'-'*50)
        else:
            book = load_workbook(filepath)  # 读取已经存有数据的excel,如果文件损坏，会报异常，创建好文件后第一次到这里时不会出问题

            if sheet_name in book.sheetnames:  #如果在excel中存在这个模型的参数，追加
                self._append_to_sheet(book,filepath,sheet_name,new_dictionary)
            else:
                self._create_new_sheet(book,filepath,sheet_name,new_dictionary)
        print('*'*50,'hyperParameter saved', '*'*50)

    def _append_to_sheet(self,book,filepath,sheet_name,new_dictionary,flag=True):
        if flag:
            print('-'*50,"appending to the sheet:{}".format(sheet_name),'-'*50)
        df_old = pd.DataFrame(pd.read_excel(filepath, sheet_name=sheet_name))  # 读取原数据文件和表
        df_rows=df_old.shape[0]  # 获取已存在的表的数据的行数
        if not flag:  #如果是重新建表
            df_rows=0
        df = pd.DataFrame(new_dictionary, index=[df_rows + 1])  # 新的数据,index属性用于标记DataFrame中的每一行
        writer = pd.ExcelWriter(filepath,engine='openpyxl')  # 和pd.read_excel() 用于将Dataframe写入excel。xls用xlwt。xlsx用openpyxl，开了writer之后就不能用read_excel了
        writer.book = book  # 此时的writer里还只是读写器. 然后将上面读取的book复制给writer
        writer.sheets = dict((ws.title, ws) for ws in book.worksheets)  # 将原excel中的表和数据拿到

        if flag:
            df.to_excel(writer, sheet_name=sheet_name, startrow=df_rows + 1,
                    header=False)  # 将数据写入excel中的aa表,从第一个空行开始写
        else:
            df.to_excel(writer, sheet_name=sheet_name, startrow=df_rows + 1,)  # 将数据写入excel中的aa表,从第一个空行开始写
        writer.save()
        writer.close()
        pass


    def _create_new_sheet(self,book,filepath,sheet_name,new_dictionary):
        '''
        创建新表之后直接调用append
        :param book:
        :param filepath:
        :param sheet_name:
        :param new_dictionary:
        :return:
        '''
        print('-'*50,"Creating a new sheet:{}".format(sheet_name), '-'*50)
        book.create_sheet(title=sheet_name,index=len(sheet_name)+1)
        book.save(filepath)
        self._append_to_sheet(book,filepath,sheet_name,new_dictionary,flag=False)
        pass

if __name__ == '__main__':
    opt = Construct_config()
    print(os.getcwd())
    filename = './record.xlsx'
    Recorder = RecordHyperParameter({'acc':76.1},opt, filename)

    Recorder.write()